import os
import pymysql
import random
import math
from datetime import datetime, timedelta
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

# MySQL连接配置 - 使用环境变量
MYSQL_CONFIG = {
    'host': os.environ.get('DB_HOST', 'localhost'),
    'user': os.environ.get('DB_USER', 'root'),
    'password': os.environ.get('DB_PASSWORD'),
    'database': os.environ.get('DB_NAME', 'basal_adjust'),
    'port': int(os.environ.get('DB_PORT', '3306')),
    'charset': 'utf8mb4'
}

# 测试患者编号
PATIENT_NUMBER = os.environ.get('TEST_PATIENT_NUMBER', 'test001')

# 模拟参数
BASE_GLUCOSE = 100  # 基础血糖值(mg/dL)，略低于标准，以便更明显地看到波动
MEAL_IMPACT = {
    'breakfast': {
        'carbs': 50,  # 碳水克数
        'impact': 2.8,  # 提高每克碳水影响，使血糖上升更明显
        'peak_time': 50,  # 延长峰值时间
        'duration': 200,  # 延长影响持续时间
    },
    'lunch': {
        'carbs': 50,
        'impact': 2.5,
        'peak_time': 50,
        'duration': 200,
    },
    'dinner': {
        'carbs': 20,
        'impact': 3.0,  # 晚餐的影响更大
        'peak_time': 50,
        'duration': 200,
    }
}

# 胰岛素参数 - 调整剂量使波动更明显
INSULIN_IMPACT = {
    'breakfast': {
        'dose': 4,  # 减少剂量，使餐后血糖上升更明显
        'impact': 30,
        'onset': 15,
        'peak': 75,  # 延长峰值时间
        'duration': 240,
    },
    'lunch': {
        'dose': 4,
        'impact': 30,
        'onset': 15,
        'peak': 75,
        'duration': 240,
    },
    'dinner': {
        'dose': 1.5,  # 减少剂量，使晚餐后血糖高于目标值
        'impact': 30,
        'onset': 15,
        'peak': 75,
        'duration': 240,
    }
}

# 设置餐食时间
MEAL_TIMES = {
    'breakfast': '08:00:00',  # 早餐时间
    'lunch': '12:00:00',      # 午餐时间
    'dinner': '18:00:00'      # 晚餐时间
}

def gaussian(x, mean, std, amplitude):
    """高斯分布函数，用于模拟餐后血糖上升和胰岛素作用"""
    return amplitude * math.exp(-((x - mean) ** 2) / (2 * std ** 2))

def meal_effect(minutes_since_meal, meal_type):
    """计算餐食对血糖的影响"""
    if meal_type not in MEAL_IMPACT:
        return 0
    
    params = MEAL_IMPACT[meal_type]
    if minutes_since_meal <= 0 or minutes_since_meal > params['duration']:
        return 0
    
    # 使用高斯函数模拟餐后血糖上升
    effect = gaussian(minutes_since_meal, params['peak_time'], 30, 
                      params['carbs'] * params['impact'])
    return max(0, effect)

def insulin_effect(minutes_since_injection, meal_type):
    """计算胰岛素对血糖的影响"""
    if meal_type not in INSULIN_IMPACT:
        return 0
    
    params = INSULIN_IMPACT[meal_type]
    if minutes_since_injection <= 0 or minutes_since_injection > params['duration']:
        return 0
    
    # 胰岛素起效延迟
    if minutes_since_injection < params['onset']:
        return 0
    
    # 使用高斯函数模拟胰岛素降糖作用
    effect = gaussian(minutes_since_injection, params['peak'], 40, 
                      params['dose'] * params['impact'])
    return max(0, effect)

def generate_realistic_cgm_data(start_date_str='2025-05-20'):
    """生成更逼真的CGM数据，模拟三餐和胰岛素注射的影响"""
    
    start_date = datetime.strptime(start_date_str, '%Y-%m-%d')
    
    # 生成24小时的数据，每5分钟一个点
    data_points = []
    
    for minutes in range(0, 24*60, 5):  # 每5分钟
        current_time = start_date + timedelta(minutes=minutes)
        current_glucose = BASE_GLUCOSE
        
        # 添加基础的随机波动
        current_glucose += random.uniform(-5, 5)
        
        # 计算每餐的影响
        for meal_name, meal_time_str in MEAL_TIMES.items():
            meal_time = datetime.strptime(f"{start_date_str} {meal_time_str}", 
                                        '%Y-%m-%d %H:%M:%S')
            
            # 餐食影响
            minutes_since_meal = (current_time - meal_time).total_seconds() / 60
            meal_glucose_effect = meal_effect(minutes_since_meal, meal_name)
            current_glucose += meal_glucose_effect
            
            # 胰岛素影响（假设餐前15分钟注射）
            injection_time = meal_time - timedelta(minutes=15)
            minutes_since_injection = (current_time - injection_time).total_seconds() / 60
            insulin_glucose_effect = insulin_effect(minutes_since_injection, meal_name)
            current_glucose -= insulin_glucose_effect
        
        # 添加昼夜节律影响
        hour = current_time.hour
        if 2 <= hour <= 6:  # 凌晨稍低
            current_glucose -= 5
        elif 6 <= hour <= 8:  # 黎明现象
            current_glucose += 10
        
        # 确保血糖在合理范围内
        current_glucose = max(40, min(400, current_glucose))
        
        data_points.append((current_time.strftime('%Y-%m-%d %H:%M:%S'), 
                          round(current_glucose, 1)))
    
    return data_points

def create_table_if_not_exists():
    """创建CGM数据表（如果不存在）"""
    try:
        # 检查数据库密码是否配置
        if not MYSQL_CONFIG['password']:
            print("错误：数据库密码未配置。请在.env文件中设置DB_PASSWORD")
            return False
            
        conn = pymysql.connect(**MYSQL_CONFIG)
        cursor = conn.cursor()
        
        table_name = f"cgm_{PATIENT_NUMBER}"
        
        create_table_sql = f"""
        CREATE TABLE IF NOT EXISTS `{table_name}` (
            id INT AUTO_INCREMENT PRIMARY KEY,
            sg_date DATETIME NOT NULL,
            sgv FLOAT NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            INDEX idx_sg_date (sg_date)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        """
        
        cursor.execute(create_table_sql)
        conn.commit()
        print(f"表 {table_name} 检查/创建完成")
        
        cursor.close()
        conn.close()
        return True
        
    except Exception as e:
        print(f"创建表失败: {e}")
        return False

def insert_cgm_data_to_db(cgm_data):
    """将CGM数据插入数据库"""
    try:
        # 检查数据库密码是否配置
        if not MYSQL_CONFIG['password']:
            print("错误：数据库密码未配置。请在.env文件中设置DB_PASSWORD")
            return
            
        conn = pymysql.connect(**MYSQL_CONFIG)
        cursor = conn.cursor()
        
        table_name = f"cgm_{PATIENT_NUMBER}"
        
        # 清除当天的旧数据
        delete_sql = f"DELETE FROM `{table_name}` WHERE DATE(sg_date) = DATE(%s)"
        cursor.execute(delete_sql, (cgm_data[0][0],))  # 使用第一个数据点的日期
        deleted_count = cursor.rowcount
        print(f"删除了 {deleted_count} 条旧数据")
        
        # 插入新数据
        insert_sql = f"INSERT INTO `{table_name}` (sg_date, sgv) VALUES (%s, %s)"
        cursor.executemany(insert_sql, cgm_data)
        
        conn.commit()
        print(f"成功插入 {len(cgm_data)} 条CGM数据到表 {table_name}")
        
        cursor.close()
        conn.close()
        
    except Exception as e:
        print(f"插入数据失败: {e}")

def print_data_summary(cgm_data):
    """打印数据摘要"""
    if not cgm_data:
        print("没有数据可显示")
        return
    
    glucose_values = [point[1] for point in cgm_data]
    
    print(f"\n数据摘要:")
    print(f"  数据点数量: {len(cgm_data)}")
    print(f"  时间范围: {cgm_data[0][0]} 到 {cgm_data[-1][0]}")
    print(f"  血糖范围: {min(glucose_values):.1f} - {max(glucose_values):.1f} mg/dL")
    print(f"  平均血糖: {sum(glucose_values)/len(glucose_values):.1f} mg/dL")
    
    # 目标范围分析
    in_range = len([g for g in glucose_values if 70 <= g <= 180])
    print(f"  目标范围内时间: {in_range/len(glucose_values)*100:.1f}%")

def main():
    """主函数"""
    print("CGM数据生成器")
    print("=" * 30)
    
    # 检查环境变量配置
    if not MYSQL_CONFIG['password']:
        print("错误：数据库密码未配置")
        print("请执行以下步骤：")
        print("1. 复制 env.example 为 .env")
        print("2. 在 .env 文件中设置 DB_PASSWORD=你的数据库密码")
        return
    
    print(f"连接到数据库: {MYSQL_CONFIG['host']}:{MYSQL_CONFIG['port']}/{MYSQL_CONFIG['database']}")
    print(f"患者编号: {PATIENT_NUMBER}")
    
    # 创建表
    if not create_table_if_not_exists():
        return
    
    # 生成数据
    target_date = '2025-05-20'
    print(f"正在生成 {target_date} 的CGM数据...")
    
    cgm_data = generate_realistic_cgm_data(target_date)
    
    # 打印摘要
    print_data_summary(cgm_data)
    
    # 插入数据库
    insert_cgm_data_to_db(cgm_data)
    
    print("CGM数据生成完成!")

if __name__ == "__main__":
    main() 